package com.hebeiboruan.controller.system;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hebeiboruan.cache.service.CacheService;
import com.hebeiboruan.common.HttpMessage;
import com.hebeiboruan.common.uitl.HttpUtil;
import com.hebeiboruan.common.uitl.JwtUtils;
import com.hebeiboruan.common.exception.CommonException;
import com.hebeiboruan.common.exception.ServiceResultEnum;
import com.hebeiboruan.common.exception.system.user.UserException;
import com.hebeiboruan.common.exception.system.user.UserResultEnum;
import com.hebeiboruan.common.uitl.CheckUtil;
import com.hebeiboruan.common.uitl.LoggerUtil;
import com.hebeiboruan.entity.DTO.system.RegisterUser;
import com.hebeiboruan.entity.DTO.system.SearchUserDTO;
import com.hebeiboruan.entity.system.User;
import com.hebeiboruan.entity.system.UserRole;
import com.hebeiboruan.user.listener.UserListener;
import com.hebeiboruan.userRole.service.UserRoleService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.impl.DefaultClaims;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import com.hebeiboruan.user.service.UserService;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 用户控制器
 * @author 刘焕林
 * @date 2023/11/02
 */
@RestController
@RequestMapping("/user")
public class UserController {
    @Value("${project.staticPath}")
    private String staticPath;
    @Value("${project.verificationCode}")
    private String verificationCode;
    private static Logger log = LoggerFactory.getLogger(UserController.class);
    private UserService userService;
    private UserRoleService userRoleService;
    private RedisTemplate redisTemplate;
    private CacheService cacheService;
    @Autowired
    public void setCacheService(CacheService cacheService) {
        this.cacheService = cacheService;
    }

    @Autowired
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Autowired
    public void setUserRoleService(UserRoleService userRoleService) {
        this.userRoleService = userRoleService;
    }

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
    @GetMapping("/getAllUser/{page}/{limit}")
    public HttpMessage getAllUser(@PathVariable Integer page,@PathVariable Integer limit){
        HttpMessage.isBlank(page,limit);
      return new HttpMessage(userService.page(new Page<>(page,limit)));
    }

    /**
     * 条件查询
     * @param search
     * @return {@link HttpMessage}
     */
    @PostMapping("/searchUser")
    public HttpMessage searchUser(SearchUserDTO search){
       HttpMessage.isBlank(search.getPage(),search.getLimit());
        QueryWrapper<User> wrapper=new QueryWrapper<>();
        if (search.getUserAccount() != null) {
            wrapper.like("user_account",search.getUserAccount());
        }
        if (search.getUserName() != null) {
            wrapper.like("user_name",search.getUserName());
        }
        if(search.getUserPhone()!=null){
            wrapper.like("user_phone",search.getUserPhone());
        }
        if (search.getUserEmail() != null) {
            wrapper.like("user_email",search.getUserEmail());
        }
        return HttpMessage.data(userService.page(new Page<>(search.getPage(),search.getLimit()),wrapper));
    }
    @PutMapping("/addUser")
    public HttpMessage addUser(User user, HttpServletRequest request){
        HttpMessage.isBlank(user.getUserAccount(),user.getUserPassword());
        User userAccount = userService.getUser(user.getUserAccount());
        if(userAccount!=null){
            return new HttpMessage(UserResultEnum.ACCOUNT_REPETITION);
        }
        if(user.getUserEmail()!=null){
            if(!CheckUtil.email(user.getUserEmail())){
                return new HttpMessage(ServiceResultEnum.EMAIL_ERROR);
            }
        }
        if (user.getUserPhone() != null) {
            if(!CheckUtil.phone(user.getUserPhone())){
                return new HttpMessage(ServiceResultEnum.PHONE_ERROR);
            }
        }
        try {
        userService.save(user);
        return HttpMessage.result(ServiceResultEnum.INSERT_TRUE);
        }catch (Exception e){
            throw new CommonException(ServiceResultEnum.INSERT_ERROR,e,request);
        }
    }
    @PostMapping("/editUser")
    public HttpMessage editUser(User user, HttpServletRequest request){
        HttpMessage.isBlank(user.getUserAccount(),user.getUserPassword(),user.getUserNo());
        User userAccount = userService.getUser(user.getUserAccount());
        if(userAccount==null){
            return  HttpMessage.result(UserResultEnum.ACCOUNT_IS_NULL);
        }
        if(user.getUserEmail()!=null){
            if(!CheckUtil.email(user.getUserEmail())){
                return  HttpMessage.result(ServiceResultEnum.EMAIL_ERROR);
            }
        }
        if (user.getUserPhone() != null) {
            if(!CheckUtil.phone(user.getUserPhone())){
                return  HttpMessage.result(ServiceResultEnum.PHONE_ERROR);
            }
        }
        try {
            userService.updateById(user);
            return  HttpMessage.result(ServiceResultEnum.UPDATE_TRUE);
        }catch (Exception e){
            throw new CommonException(ServiceResultEnum.UPDATE_ERROR,e,request);
        }
    }
    @DeleteMapping("/removeUser/{userNo}")
    public HttpMessage removeUser(@PathVariable Integer userNo,HttpServletRequest request){
        HttpMessage.isBlank(userNo);
        try {
            userService.removeById(userNo);
            return  HttpMessage.result(ServiceResultEnum.REMOVE_TRUE);
        }catch (Exception e){
            throw new CommonException(ServiceResultEnum.REMOVE_ERROR,e,request);
        }

    }

    /**
     * 检查用户是否存在
     * @param userAccount
     * @return {@link HttpMessage}
     */
    @GetMapping("/check/{userAccount}")
    public HttpMessage check(@PathVariable String userAccount){
        HttpMessage.isBlank(userAccount);
        long count = userService.count(new QueryWrapper<User>().eq("user_account", userAccount));
        if(count>0){
        return  HttpMessage.result(UserResultEnum.CHECK_COUNT_TRUE);
        }else {
        return  HttpMessage.result(UserResultEnum.CHECK_COUNT_NULL);
        }
    }

    /**
     * 登录
     * @param account
     * @param password
     * @param code
     * @param value
     * @return {@link HttpMessage}<{@link String}>
     */
    @PostMapping("/login")
    public HttpMessage<String> login(String account,String password,String code,String value,HttpServletRequest request){
        String verificationCodeValue = userService.getVerificationCodeValue(code);
        if(verificationCodeValue==null||verificationCodeValue.isEmpty()){
            return  HttpMessage.result(UserResultEnum.VERIFICATION_CODE_NULL);
        }
        if(!value.equals(verificationCodeValue)){
            return  HttpMessage.result(UserResultEnum.VERIFICATION_CODE_ERROR);
        }
        User login = userService.Login(account, password);
        userService.update(new UpdateWrapper<User>()
                .set("user_ip", HttpUtil.getIp(request))
                .setSql("user_login_date=now()")
                .eq("user_no",login.getUserNo()));
            Claims claims=new DefaultClaims();
            claims.put("userNo",login.getUserNo());
            String jwtTokenRsa = JwtUtils.getJWTTokenRsa(claims);
            cacheService.userPower(jwtTokenRsa,userService.getUserPower(login.getUserNo()),login.getUserNo());
            return  HttpMessage.data(jwtTokenRsa);
    }

    @PostMapping("/register")
    public HttpMessage<String> register(RegisterUser registerUser, HttpServletRequest request){
        String verificationCodeValue = userService.getVerificationCodeValue(registerUser.getCode());
        if(verificationCodeValue==null||verificationCodeValue.isEmpty()){
            return  HttpMessage.result(UserResultEnum.VERIFICATION_CODE_NULL);
        }
        if(!registerUser.getValue().equals(verificationCodeValue)){
            return  HttpMessage.result(UserResultEnum.VERIFICATION_CODE_ERROR);
        }
        if(!registerUser.getPassword().equals(registerUser.getConfirmPassword())){
            return HttpMessage.result(UserResultEnum.CONFIRM_ERROR);
        }
        User user = userService.getUser(registerUser.getAccount());
        if(user!=null){
            return HttpMessage.result(UserResultEnum.ACCOUNT_REPETITION);
        }
        user=new User(registerUser);
        user.setUserIp(HttpUtil.getIp(request));
        user.setUserLoginDate(DateUtil.format(new Date(),"yyyy-MM-dd HH-mm-ss"));
        userService.save(user);
        UserRole userRole=new UserRole();
        userRole.setRole(817262600);
        //817262600是用户角色的编号
        userRole.setUser(user.getUserNo());
        userRoleService.save(userRole);
        user.setUserNo(user.getUserNo());
        Claims claims=new DefaultClaims();
        claims.put("userNo",user.getUserNo());
        String jwtTokenRsa = JwtUtils.getJWTTokenRsa(claims);
        cacheService.userPower(jwtTokenRsa,userService.getUserPower(user.getUserNo()),user.getUserNo());
        return  HttpMessage.data(jwtTokenRsa);
    }
    /**
     * 生成验证码
     * @return {@link HttpMessage}
     */
    @GetMapping("/verificationCode")
    public HttpMessage verificationCode(){
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100);
        Snowflake snowflake = IdUtil.getSnowflake(1, 1);
        String id =String.valueOf( snowflake.nextId());
        lineCaptcha.write(staticPath+"/"+verificationCode+"/"+id+".png");
        userService.insertVerificationCode(id,lineCaptcha.getCode());
        Map map=new HashMap();
        map.put("id",id);
        map.put("path",verificationCode);
        return  HttpMessage.data(map);
    }

    /**
     * 验证验证码
     * @param code
     * @param value
     * @return {@link HttpMessage}
     */
    @PostMapping("/verification")
    public HttpMessage verification(String code,String value){
        String verificationCodeValue = userService.getVerificationCodeValue(code);
        if(verificationCodeValue==null||verificationCodeValue.isEmpty()){
            return  HttpMessage.result(UserResultEnum.VERIFICATION_CODE_NULL);
        }
        if(!value.equals(verificationCodeValue)){
            return  HttpMessage.result(UserResultEnum.VERIFICATION_CODE_ERROR);
        }
        return  HttpMessage.result(UserResultEnum.VERIFICATION_CODE_TRUE);
    }

    /**
     * 批量删除
     * @param id
     * @return {@link HttpMessage}
     */
    @DeleteMapping("/batchRemoveUser/{id}")
    public HttpMessage batchRemoveUser(@PathVariable String id){
        HttpMessage.isBlank(id);
        try{
            userService.removeBatchByIds(Arrays.asList(id.split(",")));
            return  HttpMessage.result(ServiceResultEnum.REMOVE_TRUE);
        }catch (Exception e){
            throw new CommonException(ServiceResultEnum.BATCH_REMOVE_ERROR,e);
        }

    }

    /**
     * 批量新增用户
     * @param user
     * @return {@link HttpMessage}
     */
    @PostMapping("/batchAddUser")
    public HttpMessage batchAddUser(@RequestParam("user")List<MultipartFile> user) {
            user.forEach(file->{
                try {
                    EasyExcel.read(file.getInputStream(), User.class, new UserListener(userService)).sheet().doRead();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
        return  HttpMessage.result(ServiceResultEnum.BATCH_INSERT_TRUE);
    }

    /**
     * 批量导出
     * @param user
     * @return {@link HttpMessage}
     */
    @PostMapping("/batchOutUser")
    public void batchOutUser(@RequestParam("user") List<String> user, HttpServletResponse response) throws IOException {
      try{
          response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
          response.setCharacterEncoding("utf-8");
          //防止乱码
          String fileName ="D:/"+ URLEncoder.encode("userData:"+LocalDateTime.now().toString(), "UTF-8").replaceAll("\\+", "%20")+".xlsx";
         List<User> userData=new ArrayList<>();
            user.forEach(item->{
                try {
                    userData.add( new ObjectMapper().readValue(item,User.class));
                } catch (JsonProcessingException e) {
                    throw new RuntimeException(e);
                }
            });
          response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

          EasyExcel.write(response.getOutputStream(), User.class).autoCloseStream(Boolean.FALSE).sheet("数据").doWrite(userData);

      }catch (Exception e){
          response.reset();
          response.setContentType("application/json");
          response.setCharacterEncoding("utf-8");

          response.getWriter().println(new HttpMessage(ServiceResultEnum.BATCH_OUT_ERROR));
      }
    }

    @GetMapping("/getUserRole/{user}")
    public HttpMessage getUserRole(@PathVariable Integer user){
        HttpMessage.isBlank(user);
        List<UserRole> list = userRoleService.list(new QueryWrapper<UserRole>().eq("user", user));
        return  HttpMessage.data(list);
    }
    @PostMapping("/addUserRole")
    public HttpMessage addUserPower(Integer user,@RequestParam(value = "role",required = false) List<Integer> role){
        HttpMessage.isBlank(user);
        List<UserRole> userRoles=new ArrayList<>();
        try {
            userRoleService.remove(new QueryWrapper<UserRole>().eq("user",user));
            if (role != null) {
                role.forEach(item->{
                    userRoles.add(new UserRole(user,item));
                });
                userRoleService.saveBatch(userRoles);
            }
            return  HttpMessage.result(ServiceResultEnum.INSERT_TRUE);
        }catch (Exception e){
            throw new UserException(UserResultEnum.INSERT_USER_ERROR);
        }
    }


}
